package com.quik.web.front.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.quik.common.Constants;
import com.quik.entity.BillingItem;
import com.quik.entity.BizBilling;
import com.quik.entity.BizBillingChessRoom;
import com.quik.entity.BizBillingItem;
import com.quik.entity.BizBillingRelatedItem;
import com.quik.entity.DtaProduct;
import com.quik.entity.Statistics;
import com.quik.entity.SysSystemCode;
import com.quik.entity.DtaToken;
import com.quik.util.Tools;
import com.quik.web.base.mapper.PubSystemDao;
import com.quik.web.front.mapper.ConsultBillingDao;
import com.quik.web.front.mapper.ConsultTokenDao;

/**
 * 功能说明： 实现ConsultTokenService接口，处理手牌的业务逻辑
 * 
 * @author jenny
 * 
 */
@Service
public class ConsultTokenServiceImpl extends ConsultBaseService implements
		ConsultTokenService {

	@Autowired
	private ConsultTokenDao dao;

	@Autowired
	private PubSystemDao systemDao;

	@Autowired
	private ConsultBillingDao billingDao;

	/**
	 * 查询手牌列表
	 * 
	 * @param tokenType
	 *            手牌类型
	 * @param status
	 *            手牌状态
	 * @return
	 * @throws Exception
	 */
	@Override
	public List findTokenList(Integer tokenType, String status)
			throws Exception {
		String section = Tools.getSection(DtaToken.TABLE_NAME,
				Constants.SYSTEM_CODE_TOKENSTATUS);

		List tokenList = dao.findTokenList(tokenType, status, section);
		return tokenList;
	}

	/**
	 * 查询手牌类型列表
	 * 
	 * @return
	 * @throws Exception
	 */
	@Override
	public List findTokenTypeList() throws Exception {
		List tokenTypeList = dao.findTokenTypeList();
		return tokenTypeList;
	}

	/**
	 * 查询手牌状态列表
	 * 
	 * @return
	 * @throws Exception
	 */
	@Override
	public List findTokenStatusList() throws Exception {
		String section = Tools.getSection(DtaToken.TABLE_NAME,
				Constants.SYSTEM_CODE_TOKENSTATUS);
		return systemDao.findSystemCodeBySection(section);
	}

	/**
	 * 统计手牌状态列表
	 * 
	 * @return
	 * @throws Exception
	 */
	@Override
	public List<Statistics> findTokenStatList() throws Exception {
		List<Statistics> tokenStatList = dao
				.findTokenStatList(Tools.getSection(DtaToken.TABLE_NAME,
						Constants.SYSTEM_CODE_TOKENSTATUS));
		return tokenStatList;
	}

	/**
	 * 根据手牌、手牌类型、手牌状态查询手牌数量
	 * 
	 * @param tokenNo
	 * @param tokenType
	 * @param status
	 * @return
	 * @throws Exception
	 */
	@Override
	public int findTokenCount(String tokenNo, Integer tokenType, String status)
			throws Exception {
		int count = dao.findTokenCount(tokenNo, tokenType, status,
				Tools.getSection(DtaToken.TABLE_NAME,
						Constants.SYSTEM_CODE_TOKENSTATUS));
		return count;
	}

	/**
	 * 根据手牌、手牌状态、手牌类型查询手牌列表（分页）
	 * 
	 * @param tokenNo
	 * @param tokenType
	 * @param status
	 * @param intPage
	 * @param pageSize
	 * @return
	 * @throws Exception
	 */
	@Override
	public List findTokenList(String tokenNo, Integer tokenType, String status,
			Integer intPage, Integer pageSize) throws Exception {
		List tokenList = dao.findTokenList(tokenNo, tokenType, status,
				Tools.getSection(DtaToken.TABLE_NAME,
						Constants.SYSTEM_CODE_TOKENSTATUS), intPage, pageSize);
		return tokenList;
	}

	/**
	 * 开手牌 1. 新增biz_billing，生成主帐单 2. 新增biz_billing_related_item，与主帐单绑定关系 3.
	 * 若绑定商品的手牌，将生成一条biz_billing_item信息,判断产品是棋牌还是服务，
	 * 对应biz_billing_chess_room和biz_billing_service表进行处理 4. 更新手牌的状态
	 * 
	 * @param tokenNo
	 *            手牌
	 * @param contactStaffNo
	 *            推荐人
	 * @param user
	 *            创建用户
	 * @throws Exception
	 */
	@Override
	public void openToken(String tokenNo, String contactStaffNo, String user)
			throws Exception {
		this.openTokens(new String[]{tokenNo}, contactStaffNo, user);
	}

	@Override
	public BizBilling openTokens(String[] tokenNos, String contactStaffNo, String user)
			throws Exception {
		// 1.新增biz_billing
		String billingNo = Tools.generateBillingNo(systemDao.findBillingNo()); // 获得帐单编号
		BizBilling bizBilling = new BizBilling();
		bizBilling.setBilling_no(billingNo);
		bizBilling.setContact_staff_no(contactStaffNo);
		bizBilling.setCrt_user(user);
		bizBilling.setIf_master(BizBilling.MASTER_YES);
		Integer billingId = billingDao.addBizBilling(bizBilling);
		for (String tokenNo : tokenNos) {
			// 2.新增biz_billing_related_item表
			BizBillingRelatedItem relatedItem = new BizBillingRelatedItem();
			relatedItem.setBilling_id(billingId);
			relatedItem.setItem_no(tokenNo);
			relatedItem.setItem_type(BizBillingRelatedItem.ITEM_TYPE_TOKEN);
			relatedItem.setCrt_user(user);
			billingDao.addBizBillingRelatedItem(relatedItem);

			// 3.如果手牌绑定商品，则新增biz_billing_item
			DtaProduct product = dao.findTokenBoundProduct(tokenNo);
			if (product != null && product.getProduct_no().length() > 0) {
				BizBillingItem billingItem = new BizBillingItem();
				billingItem.setBilling_id(billingId);
				billingItem.setProduct_no(product.getProduct_no());
				billingItem.setQty(1);
				billingItem.setToken_no(tokenNo);
				billingItem.setIs_free(BizBillingItem.STATUS_NO);
				billingItem.setIs_subtract(BizBillingItem.STATUS_NO);
				billingItem.setContact_staff_no(contactStaffNo);
				billingItem.setPrice(product.getPrice());
				billingItem.setCrt_user(user);
				billingItem.setStatus(BizBillingItem.BILLING_ITEM_STATUS_NORMAL);
				billingItem.setProduct_name(product.getProduct_name());
				billingDao.addBizBillingItem(billingItem);

				if (product.getIf_chess_room().equals(DtaProduct.OPTION_FOR_YES)) {
					List systemList = systemDao.findSystemCodeBySection(Tools
							.getSection(BizBillingChessRoom.TABLE_NAME,
									Constants.SYSTEM_CODE_CALCMODE));
					SysSystemCode systemCode = (SysSystemCode) systemList
							.get(0);
					billingDao.addBizBillingChessRoom(getBizBillingChessRoom(
							billingItem.getId(),
							Integer.parseInt(systemCode.getName()), user));
				}
				if (product.getIf_need_worker().equals(DtaProduct.OPTION_FOR_YES)) {
					billingDao.addBizBillingService(getBizBillingService(
							billingItem.getId(), user));
				}
			}

			dao.updateTokenStatus(tokenNo, DtaToken.TOKEN_STATUS_USED, user);
		}
		return bizBilling;
	}

	/**
	 * 根据手牌号查询手牌明细项进行展示
	 * 
	 * @param tokenNo
	 * @return
	 * @throws Exception
	 */
	public BillingItem findBillingItemByTokenNo(String tokenNo)
			throws Exception {
		BillingItem billingItem = dao.findBillingItemByTokenNo(tokenNo,
				BizBilling.STATUS_ACTIVE);
		return billingItem;
	}

	/**
	 * 关联手牌 1.新增biz_billing_related_item 2.如果已经关联商品，新增biz_billing_item
	 * 3.更新token状态
	 * 
	 * @param tokenNo
	 *            手牌
	 * @param billingNo
	 *            关联的帐单
	 * @param staffNo
	 *            操作员
	 * @throws Exception
	 */
	public void relateToken(String tokenNo, String billingNo,
			String contactStaffNo, String staffNo) throws Exception {
		// 1.新增biz_billing_related_item
		Integer billingId = billingDao.findBillingIdByBillingNo(billingNo);

		BizBillingRelatedItem relatedItem = new BizBillingRelatedItem();
		relatedItem.setBilling_id(billingId);
		relatedItem.setItem_type(BizBillingRelatedItem.ITEM_TYPE_TOKEN);
		relatedItem.setCrt_user(staffNo);
		relatedItem.setItem_no(tokenNo);
		billingDao.addBizBillingRelatedItem(relatedItem);

		// 2.新增biz_billing_item
		DtaProduct product = dao.findTokenBoundProduct(tokenNo);
		if (product != null && product.getProduct_no().length() > 0) {
			BizBillingItem billingItem = new BizBillingItem();
			billingItem.setBilling_id(billingId);
			billingItem.setProduct_no(product.getProduct_no());
			billingItem.setQty(1);
			billingItem.setToken_no(tokenNo);
			billingItem.setIs_free(BizBillingItem.STATUS_NO);
			billingItem.setIs_subtract(BizBillingItem.STATUS_NO);
			billingItem.setContact_staff_no(contactStaffNo);
			billingItem.setPrice(product.getPrice());
			billingItem.setStatus(BizBillingItem.STATUS_ORDER);
			billingItem.setCrt_user(staffNo);
			billingDao.addBizBillingItem(billingItem);

			if (product.getIf_chess_room().equals(DtaProduct.OPTION_FOR_YES)) {
				List systemList = systemDao.findSystemCodeBySection(Tools
						.getSection(BizBillingChessRoom.TABLE_NAME,
								Constants.SYSTEM_CODE_CALCMODE));
				SysSystemCode systemCode = (SysSystemCode) systemList.get(0);
				billingDao.addBizBillingChessRoom(getBizBillingChessRoom(
						billingItem.getId(),
						Integer.parseInt(systemCode.getName()), staffNo));
			}
			if (product.getIf_need_worker().equals(DtaProduct.OPTION_FOR_YES)) {
				billingDao.addBizBillingService(getBizBillingService(
						billingItem.getId(), staffNo));
			}
		}

		dao.updateTokenStatus(tokenNo, DtaToken.TOKEN_STATUS_USED, staffNo);
	}

	/**
	 * 判断手牌是否空闲
	 * 
	 * @param newToken
	 * @return 如果空闲返回true，否则返回false
	 * @throws Exception
	 */
	@Override
	public boolean isFree(String newToken) throws Exception {
		DtaToken token = dao.getToken(newToken);
		if (token != null && token.getStatus().equals(DtaToken.TOKEN_STATUS_FREE))
			return true;
		else
			return false;
	}

	/**
	 * 判断手牌是否开牌
	 * 
	 * @param tokenNo
	 * @return 如果开牌返回true，否则返回false
	 * @throws Exception
	 */
	@Override
	public boolean isUsed(String tokenNo) throws Exception {
		DtaToken token = dao.getToken(tokenNo);
		if (token != null && token.getStatus().equals(DtaToken.TOKEN_STATUS_USED))
			return true;
		else
			return false;
	}

	/**
	 * 交换手牌 1.更换biz_billing_related_item以及biz_billing_item（注意需要选择帐单为A状态的进行更换）
	 * 2.dta_token表的状态
	 * 
	 * @param srcToken
	 *            源手牌
	 * @param newToken
	 *            新手牌
	 * @param staffNo
	 *            操作员
	 * @throws Exception
	 */
	@Override
	public void exchangeToken(String srcToken, String newToken, String staffNo)
			throws Exception {
		billingDao.updateBizbillingRelatedItemNo(srcToken, newToken,
				BizBillingRelatedItem.ITEM_TYPE_TOKEN,
				BizBilling.STATUS_ACTIVE, staffNo);

		billingDao.updateBizBillingItemTokenNo(srcToken, newToken,
				BizBilling.STATUS_ACTIVE, staffNo);

		// 更新源手牌状态为空闲
		dao.updateTokenStatus(srcToken, DtaToken.TOKEN_STATUS_FREE, staffNo);
		// 更新新手牌状态为占用
		dao.updateTokenStatus(newToken, DtaToken.TOKEN_STATUS_USED, staffNo);
	}

	/**
	 * 根据手牌号查询手牌详情
	 * 
	 * @param tokenNo
	 * @return
	 * @throws Exception
	 */
	@Override
	public DtaToken getTokenByTokenNo(String tokenNo) throws Exception {
		DtaToken token = dao.getTokenByTokenNo(tokenNo);
		return token;
	}

	/**
	 * 检查手牌是否开牌(以dta_token中的状态为准)
	 * 
	 * @param tokenNo
	 * @return 已开牌返回true, 否则返回false
	 * @throws Exception
	 */
	@Override
	public boolean isToken(String tokenNo) throws Exception {
		DtaToken token = dao.getToken(tokenNo);
		if (token != null && token.getStatus().equals(DtaToken.TOKEN_STATUS_USED))
			return true;
		else
			return false;
	}

	/**
	 * 根据手牌绑定新开牌
	 * 
	 * @param boundToken
	 * @param relateToken
	 * @param staffNo
	 * @throws Exception
	 */
	@Override
	public void relateByToken(String boundToken, String[] relateToken,
			String staffNo) throws Exception {
		Integer billingId = billingDao.findBillingIdByItemNo(boundToken,
				BizBillingRelatedItem.ITEM_TYPE_TOKEN);

		for (String relateTokenNo : relateToken) {
			BizBillingRelatedItem relatedItem = new BizBillingRelatedItem();
			relatedItem.setBilling_id(billingId);
			relatedItem.setItem_type(BizBillingRelatedItem.ITEM_TYPE_TOKEN);
			relatedItem.setCrt_user(staffNo);
			relatedItem.setItem_no(relateTokenNo);
			billingDao.addBizBillingRelatedItem(relatedItem);

			// 2.新增biz_billing_item
			DtaProduct product = dao.findTokenBoundProduct(relateTokenNo);
			if (product != null && product.getProduct_no().length() > 0) {
				BizBillingItem billingItem = new BizBillingItem();
				billingItem.setBilling_id(billingId);
				billingItem.setProduct_no(product.getProduct_no());
				billingItem.setQty(1);
				billingItem.setToken_no(relateTokenNo);
				billingItem.setIs_free(BizBillingItem.STATUS_NO);
				billingItem.setIs_subtract(BizBillingItem.STATUS_NO);
				billingItem.setPrice(product.getPrice());
				billingItem.setStatus(BizBillingItem.STATUS_ORDER);
				billingItem.setCrt_user(staffNo);
				billingDao.addBizBillingItem(billingItem);

				if (product.getIf_chess_room().equals(DtaProduct.OPTION_FOR_YES)) {
					List systemList = systemDao.findSystemCodeBySection(Tools
							.getSection(BizBillingChessRoom.TABLE_NAME,
									Constants.SYSTEM_CODE_CALCMODE));
					SysSystemCode systemCode = (SysSystemCode) systemList
							.get(0);
					billingDao.addBizBillingChessRoom(getBizBillingChessRoom(
							billingItem.getId(),
							Integer.parseInt(systemCode.getName()), staffNo));
				}
				if (product.getIf_need_worker().equals(DtaProduct.OPTION_FOR_YES)) {
					billingDao.addBizBillingService(getBizBillingService(
							billingItem.getId(), staffNo));
				}
			}

			dao.updateTokenStatus(relateTokenNo, DtaToken.TOKEN_STATUS_USED,
					staffNo);
		}
	}

	@Override
	public List<SysSystemCode> findCallTurn() throws Exception {
		return this.systemDao.findSystemCodeBySection("[biz_billing_service]_CallMethod");
	}
}
